import * as THREE from 'three';
import type { CollisionResult } from './collisionDetector';

// 特效配置接口
export interface EffectsConfig {
  enableParticles: boolean;
  enableScreenShake: boolean;
  enableFlash: boolean;
  enableSound: boolean;
  particleCount: number;
  particleLifetime: number;
  shakeIntensity: number;
  shakeDuration: number;
  flashColor: number;
  flashDuration: number;
}

// 粒子特效接口
interface ParticleEffect {
  particles: THREE.Points;
  velocities: THREE.Vector3[];
  lifetimes: number[];
  maxLifetime: number;
}

/**
 * 碰撞特效系统
 * 处理碰撞时的视觉和音效反馈
 */
export class CollisionEffects {
  private scene: THREE.Scene;
  private camera: THREE.PerspectiveCamera;
  private config: EffectsConfig;
  
  // 特效状态
  private activeParticleEffects: ParticleEffect[] = [];
  private isShaking: boolean = false;
  private shakeStartTime: number = 0;
  private shakeOffset: THREE.Vector3 = new THREE.Vector3(); // 改为震动偏移量
  private flashMesh: THREE.Mesh | null = null;
  private isFlashing: boolean = false;
  private flashStartTime: number = 0;

  constructor(
    scene: THREE.Scene, 
    camera: THREE.PerspectiveCamera, 
    config?: Partial<EffectsConfig>
  ) {
    this.scene = scene;
    this.camera = camera;
    
    this.config = {
      enableParticles: true,
      enableScreenShake: true,
      enableFlash: true,
      enableSound: false,
      particleCount: 20,
      particleLifetime: 1.0,
      shakeIntensity: 0.1,
      shakeDuration: 0.3,
      flashColor: 0xff4444,
      flashDuration: 0.2,
      ...config
    };

    this.initFlashEffect();
  }

  /**
   * 初始化闪光特效
   */
  private initFlashEffect(): void {
    const geometry = new THREE.PlaneGeometry(2, 2);
    const material = new THREE.MeshBasicMaterial({
      color: this.config.flashColor,
      transparent: true,
      opacity: 0,
      depthWrite: false,
      depthTest: false
    });
    
    this.flashMesh = new THREE.Mesh(geometry, material);
    this.flashMesh.position.z = -0.1; // 放在相机前面很近的位置
    this.flashMesh.visible = false;
  }

  /**
   * 触发碰撞特效
   * @param collisions 碰撞结果数组
   */
  public triggerCollisionEffects(collisions: CollisionResult[]): void {
    if (collisions.length === 0) return;

    const primaryCollision = collisions[0]; // 使用第一个碰撞

    if (this.config.enableParticles && primaryCollision.contactPoint) {
      this.createParticleEffect(primaryCollision.contactPoint, primaryCollision.normal);
    }

    if (this.config.enableScreenShake) {
      this.startScreenShake();
    }

    if (this.config.enableFlash) {
      this.startFlashEffect();
    }

    if (this.config.enableSound) {
      this.playCollisionSound();
    }
  }

  /**
   * 创建粒子特效
   * @param position 碰撞位置
   * @param normal 碰撞法向量
   */
  private createParticleEffect(position: THREE.Vector3, normal?: THREE.Vector3): void {
    const particleGeometry = new THREE.BufferGeometry();
    const positions = new Float32Array(this.config.particleCount * 3);
    const colors = new Float32Array(this.config.particleCount * 3);
    const velocities: THREE.Vector3[] = [];

    // 生成粒子位置和速度
    for (let i = 0; i < this.config.particleCount; i++) {
      const i3 = i * 3;
      
      // 初始位置（碰撞点附近）
      positions[i3] = position.x + (Math.random() - 0.5) * 0.2;
      positions[i3 + 1] = position.y + (Math.random() - 0.5) * 0.2;
      positions[i3 + 2] = position.z + (Math.random() - 0.5) * 0.2;

      // 粒子颜色（橙红色到黄色）
      const hue = Math.random() * 0.1 + 0.05; // 橙色到红色
      const color = new THREE.Color().setHSL(hue, 0.8, 0.6);
      colors[i3] = color.r;
      colors[i3 + 1] = color.g;
      colors[i3 + 2] = color.b;

      // 计算粒子速度
      let velocity: THREE.Vector3;
      if (normal) {
        // 基于碰撞法向量的速度
        const spread = 0.5; // 散布角度
        velocity = normal.clone()
          .add(new THREE.Vector3(
            (Math.random() - 0.5) * spread,
            Math.random() * 0.5, // 向上的分量
            (Math.random() - 0.5) * spread
          ))
          .normalize()
          .multiplyScalar(Math.random() * 3 + 1);
      } else {
        // 随机方向
        velocity = new THREE.Vector3(
          (Math.random() - 0.5) * 4,
          Math.random() * 3 + 1,
          (Math.random() - 0.5) * 4
        );
      }
      
      velocities.push(velocity);
    }

    particleGeometry.setAttribute('position', new THREE.BufferAttribute(positions, 3));
    particleGeometry.setAttribute('color', new THREE.BufferAttribute(colors, 3));

    const particleMaterial = new THREE.PointsMaterial({
      size: 0.1,
      vertexColors: true,
      transparent: true,
      opacity: 0.8,
      blending: THREE.AdditiveBlending
    });

    const particles = new THREE.Points(particleGeometry, particleMaterial);
    this.scene.add(particles);

    // 创建粒子特效对象
    const effect: ParticleEffect = {
      particles,
      velocities,
      lifetimes: new Array(this.config.particleCount).fill(0),
      maxLifetime: this.config.particleLifetime
    };

    this.activeParticleEffects.push(effect);
  }

  /**
   * 开始屏幕震动
   */
  private startScreenShake(): void {
    if (this.isShaking) return;

    this.isShaking = true;
    this.shakeStartTime = Date.now();
    this.shakeOffset.set(0, 0, 0); // 重置震动偏移
  }

  /**
   * 开始闪光特效
   */
  private startFlashEffect(): void {
    if (!this.flashMesh || this.isFlashing) return;

    this.isFlashing = true;
    this.flashStartTime = Date.now();
    this.flashMesh.visible = true;
    
    // 将闪光网格添加到相机（这样它会跟随相机移动）
    this.camera.add(this.flashMesh);
  }

  /**
   * 播放碰撞音效
   */
  private playCollisionSound(): void {
    // 这里可以集成 Web Audio API 或其他音频库
    console.log('播放碰撞音效'); // 占位符
    
    // 示例：使用简单的 beep 音效
    try {
      const audioContext = new (window.AudioContext || (window as any).webkitAudioContext)();
      const oscillator = audioContext.createOscillator();
      const gainNode = audioContext.createGain();
      
      oscillator.connect(gainNode);
      gainNode.connect(audioContext.destination);
      
      oscillator.frequency.value = 200; // 低频撞击音
      oscillator.type = 'sawtooth';
      
      gainNode.gain.setValueAtTime(0.1, audioContext.currentTime);
      gainNode.gain.exponentialRampToValueAtTime(0.01, audioContext.currentTime + 0.1);
      
      oscillator.start(audioContext.currentTime);
      oscillator.stop(audioContext.currentTime + 0.1);
    } catch (error) {
      console.warn('无法播放音效:', error);
    }
  }

  /**
   * 更新特效（在渲染循环中调用）
   * @param deltaTime 时间增量
   */
  public update(deltaTime: number): void {
    this.updateParticleEffects(deltaTime);
    this.updateScreenShake();
    this.updateFlashEffect();
  }

  /**
   * 更新粒子特效
   * @param deltaTime 时间增量
   */
  private updateParticleEffects(deltaTime: number): void {
    for (let i = this.activeParticleEffects.length - 1; i >= 0; i--) {
      const effect = this.activeParticleEffects[i];
      const positions = effect.particles.geometry.attributes.position.array as Float32Array;
      const colors = effect.particles.geometry.attributes.color.array as Float32Array;
      let allParticlesDead = true;

      for (let j = 0; j < effect.velocities.length; j++) {
        const j3 = j * 3;
        effect.lifetimes[j] += deltaTime;

        if (effect.lifetimes[j] < effect.maxLifetime) {
          allParticlesDead = false;

          // 更新位置
          positions[j3] += effect.velocities[j].x * deltaTime;
          positions[j3 + 1] += effect.velocities[j].y * deltaTime;
          positions[j3 + 2] += effect.velocities[j].z * deltaTime;

          // 应用重力
          effect.velocities[j].y -= 9.8 * deltaTime;

          // 更新透明度（基于生命周期）
          const alpha = 1 - (effect.lifetimes[j] / effect.maxLifetime);
          colors[j3] *= alpha;
          colors[j3 + 1] *= alpha;
          colors[j3 + 2] *= alpha;
        }
      }

      // 标记几何体需要更新
      effect.particles.geometry.attributes.position.needsUpdate = true;
      effect.particles.geometry.attributes.color.needsUpdate = true;

      // 移除已完成的特效
      if (allParticlesDead) {
        this.scene.remove(effect.particles);
        effect.particles.geometry.dispose();
        (effect.particles.material as THREE.Material).dispose();
        this.activeParticleEffects.splice(i, 1);
      }
    }
  }

  /**
   * 更新屏幕震动
   */
  private updateScreenShake(): void {
    if (!this.isShaking) {
      this.shakeOffset.set(0, 0, 0);
      return;
    }

    const currentTime = Date.now();
    const elapsed = (currentTime - this.shakeStartTime) / 1000;

    if (elapsed > this.config.shakeDuration) {
      // 震动结束
      this.isShaking = false;
      this.shakeOffset.set(0, 0, 0);
    } else {
      // 计算震动强度（随时间衰减）
      const intensity = this.config.shakeIntensity * (1 - elapsed / this.config.shakeDuration);
      
      // 计算震动偏移量
      this.shakeOffset.set(
        (Math.random() - 0.5) * intensity,
        (Math.random() - 0.5) * intensity,
        (Math.random() - 0.5) * intensity
      );
    }
  }

  /**
   * 更新闪光特效
   */
  private updateFlashEffect(): void {
    if (!this.isFlashing || !this.flashMesh) return;

    const currentTime = Date.now();
    const elapsed = (currentTime - this.flashStartTime) / 1000;

    if (elapsed > this.config.flashDuration) {
      // 闪光结束
      this.isFlashing = false;
      this.flashMesh.visible = false;
      this.camera.remove(this.flashMesh);
    } else {
      // 更新闪光强度（快速衰减）
      const intensity = 1 - (elapsed / this.config.flashDuration);
      const opacity = intensity * 0.3; // 最大不透明度30%
      
      (this.flashMesh.material as THREE.MeshBasicMaterial).opacity = opacity;
    }
  }

  /**
   * 更新配置
   * @param newConfig 新配置
   */
  public updateConfig(newConfig: Partial<EffectsConfig>): void {
    this.config = { ...this.config, ...newConfig };
  }

  /**
   * 获取当前配置
   * @returns 当前配置
   */
  public getConfig(): EffectsConfig {
    return { ...this.config };
  }

  /**
   * 获取震动偏移量（用于相机更新）
   * @returns 震动偏移量
   */
  public getShakeOffset(): THREE.Vector3 {
    return this.shakeOffset.clone();
  }

  /**
   * 清理资源
   */
  public dispose(): void {
    // 清理活动的粒子特效
    this.activeParticleEffects.forEach(effect => {
      this.scene.remove(effect.particles);
      effect.particles.geometry.dispose();
      (effect.particles.material as THREE.Material).dispose();
    });
    this.activeParticleEffects = [];

    // 清理闪光特效
    if (this.flashMesh) {
      if (this.flashMesh.parent) {
        this.flashMesh.parent.remove(this.flashMesh);
      }
      this.flashMesh.geometry.dispose();
      (this.flashMesh.material as THREE.Material).dispose();
      this.flashMesh = null;
    }

    // 重置状态
    this.isShaking = false;
    this.isFlashing = false;
  }
}